//
//  calculator.h
//  calculator1
//
//  Created by Wong Hui Hern on 2023/10/22.
//

#ifndef calculator_h
#define calculator_h

#include <cstring>
#include <iostream>
#include <stack>
#include <cstdlib>

using namespace std;

class calculator{
private:
    string s;
    
public:
    calculator( ){}
    calculator(const string &input){get_init(input);}
    void get_init(const string &input);
    void filter();  //去掉不合规格标识符
    double calculate()const; //计算器
    void calc(stack<double> &digit,stack<char> oper)const;    //  局部计算
    double determine()const; //判断：若是不满足表达式的情况，则返回-1；若除法出现错误，返回-2；
};

void calculator::get_init(const string &input){
    s=input;
    filter();
}

void calculator::filter(){
    string output="(";
    for(char &x:s)
        if((x>='0'&&x<='9')||x=='.'||x=='+'||x=='-'||x=='*'||x=='/'||x=='('||x==')'){
            output+=x;
        }
    output+=")";
    s=output;
}

double calculator::determine()const{
    double ans=0;
    try{
        ans=calculate();
    }
    catch (int error){
        if(error==-1){
            cerr<<"ERROR"<<endl;
        }
        else if(error==-2){
            cerr<<"Math error!"<<endl;
        }
        throw error;
    }
    return ans;
}

void calculator::calc(stack<double> &digit,stack<char> oper)const{
    if(digit.empty()){
        throw -1;
    }
    char o=oper.top();
    oper.pop();
    double t1=digit.top();
    digit.pop();
    if(o=='_'){
        digit.push(-t1);
    }
    else{
        if(digit.empty()){
            throw -1;
        }
        double t2=digit.top();
        digit.pop();
        if(o=='+'){
            digit.push(t2+t1);
        }
        else if(o=='-'){
            digit.push(t2-t1);
        }
        else if(o=='*'){
            digit.push(t2*t1);
        }
        else{
            if(t1==0){
                throw -2;
            }
            digit.push(t2/t1);
        }
    }
    
}

double calculator::calculate()const{
    stack<char> oper;
    stack<double> digit;
    string temp;
    char inter='\0';
    
    for(const char x:s){
        if((x>='0'&&x<='9')||x=='.'){
            temp+=x;
        }
        else{
            if(!temp.empty()){
                digit.push(atof(temp.c_str()));     //因为temp是字符串，将其转换成字符首地址
                temp.clear();
            }
            if(x=='('){
                oper.push(x);
            }
            else if(x==')'){
                while(!oper.empty()&&oper.top()!='('){
                    try{
                        calc(digit, oper);
                    }
                    catch(int error){
                        throw error;
                    }
                    oper.pop();
                }
                if(oper.empty()||oper.top()!='(')
                    throw -1;
                else oper.pop();
                
            }
            else if(x=='*'||x=='/'){
                while(!oper.empty()&&(oper.top()=='*'||oper.top()=='/'||oper.top()=='_')){
                    try{
                        calc(digit, oper);
                    }
                    catch(int error){
                        throw error;
                    }
                }
                oper.push(x);
            }
            else if(x=='+'||x=='-'){
                while(!oper.empty()&&oper.top()!='('){
                    try{
                        calc(digit,oper);
                    }
                    catch(int error){
                        throw error;
                    }
                }
                if(inter!=')'&&!(inter>='0'&&inter<='9')&&x=='-')
                    oper.push('_');
                else oper.push(x);
            }
        }
        inter=x;
    }
    if(!oper.empty()||digit.size()!=1){
        throw -1;
    }
    return digit.top();
}
#endif /* calculator_h */
